﻿using System;
using System.Globalization;
using System.Xml;

namespace TwinHead.Frameworks
{
    /// <summary>
    /// Null값을 체크하고 Null인 경우 적당한 형식으로 변환해 줍니다.
    /// <para>Null이 아닌 경우에는 해당값을 적절하게 변환하여 원하는 형식으로 리턴합니다.</para>
    /// <para>이 클래스는 Convert클래스로 일부 대체될 수 있습니다.</para>
    /// </summary>
    public static class NoNull
    {
        /// <summary>
        /// object객체를 문자열로 변경해 줍니다.
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>만약 DBNull이거나 object가 null이면 공백 문자열을 리턴하고 값이 있다면 문자열을 반환합니다.</returns>
        public static string ToString( object obj )
        {
            try
            {
                if ((Convert.IsDBNull( obj )) || (obj == null))
                    return string.Empty;

                return Convert.ToString( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// object객체를 문자열로 변경해 줍니다.
        /// </summary>
        /// <param name="obj">객체</param>
        /// <param name="obj2">obj1이 널이면 반환 할 값</param>
        /// <returns>만약 DBNull이거나 obj가 null이면 obj2를 문자열로 변환한 값을 반환합니다.</returns>
        public static string ToString( object obj, object obj2 )
        {
            string ret = string.Empty;

            ret = ToString( obj );

            if (string.IsNullOrEmpty( ret ))
                return ToString( obj2 );

            return ret;
        }

        /// <summary>
        /// object객체를 문자열로 변경해 줍니다.
        /// </summary>
        /// <param name="obj">객체</param>
        /// <param name="trim">앞뒤의 공백을 없애줄 것인가 여부</param>
        /// <returns>만약 DBNull이거나 object가 null이면 공백문자열을 리턴하고 값이있다면 문자열을 리턴해 줍니다.</returns>
        public static string ToString( object obj, bool trim )
        {
            string strValue = ToString( obj );
            return (trim ? strValue.Trim() : strValue);
        }

        /// <summary>
        /// object객체를 문자로 변경해 줍니다.
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>
        /// 만약 DBNull이거나 object가 null이면 공백문자('\0')를 리턴하고 값이 있다면 문자를 리턴해 줍니다.
        /// </returns>
        /// <example>
        /// NoNull.ToChar(obj)는 Convert.ToChar(obj)과 같습니다.
        /// </example>
        public static char ToChar( object obj )
        {
            try
            {
                if ((Convert.IsDBNull( obj )) || (obj == null))
                    return '\0';

                return Convert.ToChar( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return '\0';
            }
        }

        /// <summary>
        /// object객체를 int형으로 변경해 줍니다.
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>만약 DBNull이거나 object가 null이면 0을 리턴하고 값이있다면 해당숫자를 리턴해 줍니다.</returns>
        /// <example>
        /// NoNull.ToInt(obj)는 Convert.ToInt32(obj)과 같습니다.
        /// </example>
        public static int ToInt( object obj )
        {
            return ToInt( obj, 0 );
        }

        /// <summary>
        /// object객체를 int형으로 변경해 줍니다.
        /// </summary>
        /// <param name="obj">객체</param>
        /// <param name="defaultValue">기본값 <para>DBNull이거나 object가 null일때 반환되는 값</para></param>
        /// <returns>만약 DBNull이거나 object가 null이면 0을 리턴하고 값이있다면 해당숫자를 리턴해 줍니다.</returns>
        /// <example>
        /// NoNull.ToInt(obj)는 Convert.ToInt32(obj)과 같습니다.
        /// </example>
        public static int ToInt( object obj, int defaultValue )
        {
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return defaultValue;

            try
            {
                return Convert.ToInt32( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// Float형으로 변환
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>객체를 Float로 변환한 값</returns>
        public static float ToFloat( object obj )
        {
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return 0.0f;

            try
            {
                return Convert.ToSingle( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return 0.0f;
            }
        }

        /// <summary>
        /// Float형으로 변환
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>객체를 Float로 변환한 값</returns>
        public static double ToDouble( object obj )
        {
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return 0;

            try
            {
                return Convert.ToDouble( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// short형으로 변환
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>객체를 short로 변환한 값</returns>
        public static short ToInt16( object obj )
        {
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return 0;

            try
            {
                return Convert.ToInt16( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return (short)0;
            }
        }

        /// <summary>
        /// long형으로 변환
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>객체를 long으로 변환한 값 0L=>0으로 수정</returns>
        public static long ToInt64( object obj )
        {
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return 0;

            try
            {
                return Convert.ToInt64( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// decimal형으로 변환
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>객체를 decimal형으로 변환한 값 0m=>0으로 수정</returns>
        public static decimal ToDecimal( object obj )
        {
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return 0;

            try
            {
                return Convert.ToDecimal( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// bool형으로 변환
        /// <para>숫자값인 경우, 0이면 false, 0이 아니면 true를 반환</para>
        /// <para>숫자 이외의 자료유형이면, bool로 형변환한 값을 반환</para>
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>객체를 bool형으로 변환한 값</returns>
        public static bool ToBoolean( object obj )
        {            
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return false;
            
            try
            {
                try
                {
                    if (Convert.ToInt32( obj, CultureInfo.InvariantCulture ) == 0)
                        return false;

                    return true;
                }
                catch
                {
                    bool val = false;

                    if (bool.TryParse( ToString( obj ), out val ))
                        return val;

                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// DateTime 객체로 변환합니다.
        /// <para>변환에 실패하면 DateTime.Now를 반환합니다.</para>
        /// </summary>
        /// <param name="obj">객체</param>
        /// <returns>객체를 DateTime형으로 변환한 값</returns>
        public static DateTime ToDateTime( object obj )
        {
            if ((Convert.IsDBNull( obj )) || (obj == null))
                return DateTime.MinValue;

            try
            {
                return Convert.ToDateTime( obj, CultureInfo.InvariantCulture );
            }
            catch
            {
                return DateTime.Now;
            }
        }

        /// <summary>
        /// 8자리 년월일을 DateTime객체로 변환합니다.
        /// <para>변환에 실패하면 DateTime.Now를 반환합니다.</para>
        /// </summary>
        /// <param name="yyyymmdd">8자리 년월일</param>
        /// <returns>변환에 실패하면 DateTime.Now를 반환합니다.</returns>
        public static DateTime ToDateTimeFrom( string yyyymmdd )
        {
            if (string.IsNullOrEmpty( yyyymmdd ) || yyyymmdd.Length < 8)
                return DateTime.Now;

            DateTime returnDate;

            try
            {
                System.Text.StringBuilder buff = new System.Text.StringBuilder(16);
                buff.AppendFormat( "{0}-{1}-{2}", yyyymmdd.Substring( 0, 4 ), yyyymmdd.Substring( 4, 2 ), yyyymmdd.Substring( 6, 2 ) );
                returnDate = DateTime.Parse( buff.ToString(), CultureInfo.InvariantCulture );
            }
            catch
            {
                returnDate = DateTime.Now;
            }
            return returnDate;
        }

        /// <summary>
        /// XmlNode에서 InnerText 값을 가져온다.
        /// </summary>
        /// <param name="node">대상노드</param>
        /// <returns>대상노드가 null이면 공백문자열을 반환하고, 그렇지 않으면 InnerText값을 반환합니다.</returns>
        public static string ToNodeValue( XmlNode node )
        {
            if (node == null)
                return string.Empty;

            return node.InnerText;
        }

        /// <summary>
        /// XmlNode에서 InnerText 값을 가져온다.
        /// </summary>
        /// <param name="node">대상노드</param>
        /// <param name="defaultValue">node가 null일 경우 기본값</param>
        /// <returns>대상노드가 null이면 defaultValue를 반환하고, 그렇지 않으면 InnerText값을 반환합니다.</returns>
        public static string ToNodeValue( XmlNode node, string defaultValue )
        {
            if (node == null)
                return defaultValue;

            return node.InnerText;
        }
    }
}
